#include <sys/shm.h>
#include <sys/ipc.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "Time.hpp"
#include "Fifo.hpp"
const char *gpathname = "/home/wmz/linux-learning/Shm";
int gproj_id = 1;

int gsize = 4096;
const mode_t gmode = 0600;

// 传输的数据
typedef struct data
{
    char state[32];
    char lasttime[48];
    char image[4000];
} data;

class Shm
{
public:
    Shm() : _shmid(-1), _shmaddr(nullptr)
    {
    }
    ~Shm()
    {
        DetachShm();
        DeleteShm();
    }
    void CreateShm()
    {
        // 1.创建shm
        _key = ftok(gpathname, gproj_id);
        // std::cout<<"k:"<<key<<std::endl;
        printf("k:0x%x\n", _key);
        _shmid = ::shmget(_key, gsize, IPC_CREAT | IPC_EXCL | gmode);
        if (_shmid < 0)
        {
            std::cout << "shmid error" << std::endl;
            return;
        }
        std::cout << "shmid:" << _shmid << std::endl;
    }
    void GetShm()
    {
        _key = ftok(gpathname, gproj_id);
        // std::cout<<"k:"<<key<<std::endl;
        printf("k:0x%x\n", _key);
        _shmid = ::shmget(_key, gsize, IPC_CREAT | gmode);
        if (_shmid < 0)
        {
            std::cout << "shmid error" << std::endl;
            return;
        }
        std::cout << "shmid:" << _shmid << std::endl;
    }
    void AttachShm()
    {
        if (_shmid < 0)
        {
            std::cout << "attach error: shmid<0" << std::endl;
            return;
        }
        _shmaddr = (char *)::shmat(_shmid, nullptr, 0);
        if (_shmaddr == (void *)-1)
        {
            std::cout << "attach error" << std::endl;
            return;
        }
        std::cout << "shmaddr:" << (void *)_shmaddr << std::endl;
        return;
    }
    void Write()
    {
        // int index = 0;
        // char ch = 'a';
        // //char *tmp = (char *)_shmaddr;
        // while (true)
        // {
        //     ((char*)_shmaddr)[index++] = ch++;
        //     sleep(5);
        // }
        Client c;
        c.OpenFileForWR();
        while (true)
        {
            data d;
            memcpy(d.state, "最新", sizeof(d.state));
            memcpy(d.lasttime, GetTime().c_str(), sizeof(d.lasttime));
            memcpy(d.image, "xxxxxxxxxxxx", sizeof(d.image));
            memcpy(_shmaddr,&d,sizeof(data));
            c.SendPipe();
            sleep(4);
        }
        c.CloseFileForWR();
    }
    void Read()
    {
        data d;
        Serve s;
        s.OpenFileForRD();
        while (true)
        {
            s.RecPipe();
            memcpy(&d, _shmaddr, sizeof(data));
            std::cout << d.state << std::endl;
            std::cout << d.lasttime << std::endl;
            std::cout << d.image << std::endl;
            sleep(2);
        }
        s.CloseFileForRD();
        // char buff[gsize + 1] = {0};
        // while (true)
        // {
        //     char *ret = (char *)memcpy(buff, _shmaddr, gsize);
        //     std::cout << ret << std::endl;
        //     sleep(1);
        // }
    }
    void DetachShm()
    {
        if (_shmaddr == nullptr)
        {
            std::cout << "detach error: _shaaddr == nullptr" << std::endl;
            return;
        }
        int ret = ::shmdt(_shmaddr);
        if (ret < 0)
        {
            std::cout << "detach error" << std::endl;
            return;
        }
        std::cout << "detach success" << std::endl;
    }
    void DeleteShm()
    {
        if (_shmid < 0)
        {
            std::cout << "delete error: shmid<0" << std::endl;
            return;
        }
        int ret1 = ::shmctl(_shmid, IPC_RMID, nullptr);
        if (ret1 < 0)
        {
            std::cout << "delete error" << std::endl;
        }
        std::cout << "delete success" << std::endl;
    }

private:
    key_t _key;
    int _shmid;
    void *_shmaddr;
};
Shm shm;